home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianLists.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  12KB  |  669 lines

  1. /*ScianLists.c
  2.   Eric Pepke
  3.   March 28, 1990
  4.   Routines for lists of things
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianNames.h"
  10. #include "ScianLists.h"
  11. #include "ScianIDs.h"
  12. #include "ScianGarbageMan.h"
  13. #include "ScianWindows.h"
  14. #include "ScianObjWindows.h"
  15. #include "ScianDraw.h"
  16.  
  17. ObjPtr listClass = NULLOBJ;
  18.  
  19. ObjPtr CopyList(list)
  20. ObjPtr list;
  21. /*Returns a copy of list*/
  22. {
  23.     ObjPtr retVal;
  24.     ThingListPtr runner;
  25.  
  26.     if (!list || !IsList(list))
  27.     {
  28.     return NULLOBJ;
  29.     }
  30.     retVal = NewList();
  31.     runner = LISTOF(list);
  32.     while (runner)
  33.     {
  34.     PostfixList(retVal, runner -> thing);
  35.     runner = runner -> next;
  36.     }
  37.     return retVal;
  38. }
  39.  
  40. static ObjPtr FindListObject(list, name)
  41. ObjPtr list;
  42. char *name;
  43. /*Finds an object with name in list.  Returns it or NULLOBJ*/
  44. {
  45.     ObjPtr retVal;
  46.     ThingListPtr runner;
  47.     ObjPtr objName;
  48.     retVal = NULLOBJ;
  49.     /*First check to see if I am the object*/
  50.     objName = GetVar(list, NAME);
  51.     if (objName && IsString(objName) && ObjectNameMatches(name, GetString(objName)))
  52.     {
  53.     if (!retVal)
  54.     {
  55.         retVal = NewList();
  56.     }
  57.     PostfixList(retVal, list);
  58.     }
  59.  
  60.     /*Now see if one of my contents is the object*/
  61.     runner = LISTOF(list);
  62.     while (runner)
  63.     {
  64.     ObjPtr foundObject;
  65.     foundObject = FindNamedObject(runner -> thing, name);
  66.     if (foundObject)
  67.     {
  68.         if (!retVal)
  69.         {
  70.         retVal = NewList();
  71.         }
  72.         AppendList(retVal, foundObject);
  73.     }
  74.     runner = runner -> next;
  75.     }
  76.     return retVal;
  77. }
  78.  
  79. static ObjPtr ForAllListObjects(list, routine)
  80. ObjPtr list;
  81. FuncTyp routine;
  82. /*Does routine on list*/
  83. {
  84.     ThingListPtr runner;
  85.  
  86.     (*routine)(list);
  87.  
  88.     /*Now do on contents*/
  89.     runner = LISTOF(list);
  90.     while (runner)
  91.     {
  92.     ForAllObjects(runner -> thing, routine);
  93.     runner = runner -> next;
  94.     }
  95.     return ObjTrue;
  96. }
  97.  
  98. ObjPtr NewList()
  99. /*Returns a new, empty list*/
  100. {
  101.     LPtr retVal;
  102.  
  103.     retVal = (LPtr) NewObject(listClass, sizeof(List) - sizeof(Thing));
  104.     if (!retVal)
  105.     {
  106.     return 0;
  107.     }
  108.     SETOBJTYPE(retVal -> thing . flags, LIST);
  109.  
  110.     retVal -> list = 0;
  111.     retVal -> lastNode = 0;
  112.  
  113.     return (ObjPtr) retVal;
  114. }
  115.  
  116. Bool PrefixList(list, thing)
  117. ObjPtr list;
  118. ObjPtr thing;
  119. /*Prefixes thing on to the beginning of list*/
  120. {
  121.     ThingListPtr newNode;
  122.     newNode = newp(ThingListElement);
  123.     if (!newNode)
  124.     {
  125.     OMErr();
  126.     return false;
  127.     }
  128.  
  129.     newNode -> thing = thing;
  130.     newNode -> next = LISTOF(list);
  131.  
  132.     if (!LISTOF(list))
  133.     {
  134.     ((LPtr) list) -> lastNode = newNode;
  135.     }
  136.  
  137.     LISTOF(list) = newNode;
  138.     return true;
  139. }
  140.  
  141. Bool AppendList(list, appList)
  142. ObjPtr list;
  143. ObjPtr appList;
  144. /*Postfixes appList on to the end of list*/
  145. {
  146.     ThingListPtr runner;
  147.     runner = LISTOF(appList);
  148.     while (runner)
  149.     {
  150.     PostfixList(list, runner -> thing);
  151.     runner = runner -> next;
  152.     }
  153.     return true;
  154. }
  155.  
  156. Bool PostfixList(list, thing)
  157. ObjPtr list;
  158. ObjPtr thing;
  159. /*Postfixes thing on to the end of list*/
  160. {
  161.     ThingListPtr newNode;
  162.  
  163.     newNode = newp(ThingListElement);
  164.     if (!newNode)
  165.     {
  166.     OMErr();
  167.     return false;
  168.     }
  169.     newNode -> thing = thing;
  170.     newNode -> next = 0;
  171.  
  172.     if (((LPtr) list) -> lastNode)
  173.     {
  174.     ((LPtr) list) -> lastNode -> next = newNode;
  175.     ((LPtr) list) -> lastNode = newNode;
  176.     }
  177.     else
  178.     {
  179.     ((LPtr) list) -> list = newNode;
  180.     ((LPtr) list) -> lastNode = newNode;
  181.     }
  182.     return true;
  183. }
  184.  
  185. int ListCount(theList) /* return number of elements in a list */
  186. ObjPtr theList;
  187. {
  188.     int n=1;
  189.     ThingListPtr p;
  190.  
  191.     if (!IsList(theList) || !(p = LISTOF(theList))) return 0;
  192.     while (p = p -> next) ++n;
  193.     return n;
  194. }
  195.  
  196. ObjPtr GetListElem(theList, index) /* return element of a list (0=first) */
  197. ObjPtr theList;
  198. int index;
  199. {
  200.     ThingListPtr p;
  201.  
  202.     if (index < 0 || !IsList(theList)
  203.     || !(p = LISTOF(theList))) return NIL;
  204.     do { if (--index < 0) return p -> thing; } while (p = p -> next);
  205.     return NIL; /* no more elements */
  206. }
  207.  
  208. int WhichListIndex(list, object)
  209. ObjPtr list, object;
  210. /*Returns index of object in list, or -1*/
  211. {
  212.     int k;
  213.     ThingListPtr runner;
  214.  
  215.     k = 0;
  216.     runner = LISTOF(list);
  217.     while (runner)
  218.     {
  219.     if (runner -> thing == object) return k;
  220.     ++k;
  221.     runner = runner -> next;
  222.     }
  223.     return -1;
  224. }
  225.  
  226. int DeleteFromList(list, thing)
  227. ObjPtr list;
  228. ObjPtr thing;
  229. /*Deletes all occurences of thing from list.  Returns the number of things
  230.   it had to delete.*/
  231. {
  232.     ThingListPtr *runner;
  233.     ThingListPtr lastNotDeleted;
  234.     int retVal;
  235.  
  236.     retVal = 0;
  237.  
  238.     lastNotDeleted = NULL;
  239.     runner = &(LISTOF(list));
  240.     while (*runner)
  241.     {
  242.     if ((*runner) -> thing == thing)
  243.     {
  244.         ThingListPtr next;
  245.         next = (*runner) -> next;
  246.         Free(*runner);
  247.         *runner = next;
  248.         ++retVal;
  249.     }
  250.     else
  251.     {
  252.         lastNotDeleted = *runner;
  253.         runner = &(*runner) -> next;
  254.     }
  255.     }
  256.     ((LPtr) list) -> lastNode = lastNotDeleted;
  257.     return retVal;
  258. }
  259.  
  260. void EmptyList(list)
  261. ObjPtr list;
  262. /*Empties list, i.e. deletes all the elements*/
  263. {
  264.     ThingListPtr *runner;
  265.  
  266.     runner = &(LISTOF(list));
  267.     while (*runner)
  268.     {
  269.         ThingListPtr next;
  270.         next = (*runner) -> next;
  271.         Free(*runner);
  272.         *runner = next;
  273.     }
  274.     ((LPtr) list) -> lastNode = NULL;
  275. }
  276.  
  277. void DisposeList(list)
  278. ObjPtr list;
  279. /*Disposes of the contents of list*/
  280. {
  281.     while (LISTOF(list))
  282.     {
  283.     ThingListPtr next;
  284.     next = LISTOF(list) -> next;
  285.     Free(LISTOF(list));
  286.     LISTOF(list) = next;
  287.     }
  288.     LISTOF(list) = 0;
  289.     Free(list);
  290. }
  291.  
  292. #ifdef GRAPHICS
  293. static void DrawRunner(runner)
  294. ThingListPtr runner;
  295. /*Draws a portion of a list starting at runner, back to front*/
  296. {
  297.     if (runner)
  298.     {
  299.         ObjPtr oneObject;
  300.     DrawRunner(runner -> next);
  301.  
  302.     oneObject = runner -> thing;
  303.     if (IsObject(oneObject))
  304.     {
  305.         DrawObject(oneObject);
  306.     }
  307.     else if (IsList(oneObject))
  308.     {
  309.         DrawList(oneObject);
  310.     }
  311.     }
  312. }
  313. #endif
  314.  
  315. void DrawList(list)
  316. ObjPtr list;
  317. /*Draws a list of objects list.*/
  318. {
  319. #ifdef GRAPHICS
  320.     ThingListPtr runner;
  321.  
  322.     runner = LISTOF(list);
  323.     DrawRunner(runner);
  324. #endif
  325. }
  326.  
  327. ObjPtr PressList(list, x, y, flags)
  328. ObjPtr list;
  329. int x, y;
  330. long flags;
  331. /*Does a press in list starting at x, y.*/
  332. {
  333. #ifdef INTERACTIVE
  334.     ThingListPtr runner;
  335.     ObjPtr current;
  336.  
  337.     current = GetVar((ObjPtr) selWinInfo, CURRENT);
  338.  
  339.     if (current)
  340.     {
  341.     /*Give the current object first dibs*/
  342.     runner = LISTOF(list);
  343.     while (runner)
  344.     {
  345.             ObjPtr oneObject;
  346.         ObjPtr test;            /*Test to see if press worked*/
  347.  
  348.         oneObject = runner -> thing;
  349.         if (oneObject == current)
  350.         {
  351.         test = PressObject(oneObject, x, y, flags);
  352.         if (IsTrue(test))
  353.         {
  354.             return test;
  355.         }
  356.         }
  357.         runner = runner -> next;
  358.     }
  359.     }
  360.  
  361.     runner = LISTOF(list);
  362.     while (runner)
  363.     {
  364.         ObjPtr oneObject;
  365.     ObjPtr test;            /*Test to see if press worked*/
  366.  
  367.     oneObject = runner -> thing;
  368.     if (oneObject != current)
  369.     {
  370.         test = PressObject(oneObject, x, y, flags);
  371.         if (IsTrue(test))
  372.         {
  373.         return test;
  374.         }
  375.     }
  376.     runner = runner -> next;
  377.     }
  378. #endif
  379.     return ObjFalse;
  380. }
  381.  
  382. ObjPtr TurnDialList(list, whichDial, delta, flags)
  383. ObjPtr list;
  384. int whichDial;
  385. real delta;
  386. long flags;
  387. /*Does a dial turn in list with whichDial by delta amount*/
  388. {
  389. #ifdef INTERACTIVE
  390.     ThingListPtr runner;
  391.     ObjPtr current;
  392.  
  393.     current = GetVar((ObjPtr) selWinInfo, CURRENT);
  394.  
  395.     if (current)
  396.     {
  397.     /*Give the current object first dibs*/
  398.     runner = LISTOF(list);
  399.     while (runner)
  400.     {
  401.             ObjPtr oneObject;
  402.         ObjPtr test;            /*Test to see if dial turn worked*/
  403.  
  404.         oneObject = runner -> thing;
  405.         if (oneObject == current)
  406.         {
  407.         test = TurnDialObject(oneObject, whichDial, delta, flags);
  408.         if (IsTrue(test))
  409.         {
  410.             return test;
  411.         }
  412.         }
  413.         runner = runner -> next;
  414.     }
  415.     }
  416.  
  417.     runner = LISTOF(list);
  418.     while (runner)
  419.     {
  420.         ObjPtr oneObject;
  421.     ObjPtr test;            /*Test to see if dial turn worked*/
  422.  
  423.     oneObject = runner -> thing;
  424.     if (oneObject != current)
  425.     {
  426.         test = TurnDialObject(oneObject, whichDial, delta, flags);
  427.         if (IsTrue(test))
  428.         {
  429.         return test;
  430.         }
  431.     }
  432.     runner = runner -> next;
  433.     }
  434. #endif
  435.     return ObjFalse;
  436. }
  437.  
  438. ObjPtr DropList(list, object, x, y)
  439. ObjPtr list, object;
  440. int x, y;
  441. /*Drops object in list at x, y.*/
  442. {
  443.     ThingListPtr runner;
  444.  
  445.     runner = LISTOF(list);
  446.     while (runner)
  447.     {
  448.         ObjPtr oneObject;
  449.     ObjPtr test;            /*Test to see if drop worked*/
  450.  
  451.     oneObject = runner -> thing;
  452.     if (IsObject(oneObject))
  453.     {
  454.         test = DropObjects(oneObject, object, x, y);
  455.         if (IsTrue(test))
  456.         {
  457.         return test;
  458.         }
  459.     }
  460.     else if (IsList(oneObject))
  461.     {
  462.         test = DropList(oneObject, object, x, y);
  463.         if (IsTrue(test))
  464.         {
  465.         return test;
  466.         }
  467.     }
  468.     runner = runner -> next;
  469.     }
  470.  
  471.     return ObjFalse;
  472. }
  473.  
  474. #ifdef PROTO
  475. ObjPtr KeyDownList(ObjPtr list, int key, long flags)
  476. #else
  477. ObjPtr KeyDownList(list, key, flags)
  478. ObjPtr list;
  479. int key;
  480. long flags;
  481. #endif
  482. /*Does a key down in list with key and flags*/
  483. {
  484.     ThingListPtr runner;
  485.     runner = LISTOF(list);
  486.     while (runner)
  487.     {
  488.         ObjPtr oneObject;
  489.     ObjPtr test;            /*Test to see if press worked*/
  490.  
  491.     oneObject = runner -> thing;
  492.     if (IsObject(oneObject))
  493.     {
  494.         ObjPtr bounds;        /*The bounds of the object*/
  495.  
  496.         test = KeyDownObject(oneObject, key, flags);
  497.         if (IsTrue(test))
  498.         {
  499.         return test;
  500.         }
  501.     }
  502.     else if (IsList(oneObject))
  503.     {
  504.         test = KeyDownList(oneObject, key, flags);
  505.         if (IsTrue(test))
  506.         {
  507.         return test;
  508.         }
  509.     }
  510.     runner = runner -> next;
  511.     }
  512.  
  513.     return ObjFalse;
  514. }
  515.  
  516.  
  517.  
  518. #ifdef PROTO
  519. ObjPtr SortListByStringVar(ObjPtr list, NameTyp id, Bool ascending)
  520. #else
  521. ObjPtr SortListByStringVar(list, id, ascending)
  522. ObjPtr list;
  523. NameTyp id;
  524. Bool ascending;
  525. #endif
  526. /*Returns a new list which is sorted by id in ascending or !ascending order.
  527.   Uses a merge sort, always a favorite of mine.  Currently it's not stable,
  528.   but that could be fixed by changing how firstHalf and secondHalf are
  529.   calculated.*/
  530. {
  531.     ObjPtr retVal;
  532.  
  533.     if (((LPtr) list) -> list == ((LPtr) list) -> lastNode)
  534.     {
  535.     /*0 or 1 elements, already sorted*/
  536.     retVal = NewList();
  537.     if (LISTOF(list))
  538.     {
  539.         PrefixList(retVal, LISTOF(list) -> thing);
  540.     }
  541.     }
  542.     else
  543.     {
  544.     ObjPtr firstHalf, secondHalf;
  545.     ThingListPtr runner, firstRunner, secondRunner;
  546.     ObjPtr var;
  547.     char *test1, *test2;
  548.     int comparison;
  549.  
  550.     /*Make first and second halves*/
  551.     firstHalf = NewList();
  552.     secondHalf = NewList();
  553.  
  554.     runner = LISTOF(list);
  555.     while (runner)
  556.     {
  557.         PostfixList(firstHalf, runner -> thing);
  558.         runner = runner -> next;
  559.         if (runner)
  560.         {
  561.         PostfixList(secondHalf, runner -> thing);
  562.         runner = runner -> next;
  563.         }
  564.     }
  565.  
  566.     /*Sort them*/
  567.     firstHalf = SortListByStringVar(firstHalf, id, ascending);
  568.     secondHalf = SortListByStringVar(secondHalf, id, ascending);
  569.  
  570.     /*Merge them*/
  571.     retVal = NewList();
  572.     firstRunner = LISTOF(firstHalf);
  573.     secondRunner = LISTOF(secondHalf);
  574.  
  575.     /*Do the main merge*/
  576.     while(firstRunner && secondRunner)
  577.     {
  578.         var = GetVar(firstRunner -> thing, id);
  579.         if (var)
  580.         {
  581.         test1 = GetString(var);
  582.         }
  583.         else
  584.         {
  585.         test1 = "";
  586.         }
  587.         var = GetVar(secondRunner -> thing, id);
  588.         if (var)
  589.         {
  590.         test2 = GetString(var);
  591.         }
  592.         else
  593.         {
  594.         test2 = "";
  595.         }
  596.         comparison = strcmp2(test1, test2);
  597.  
  598.         if (ascending)
  599.         {
  600.         if (comparison <= 0)
  601.         {
  602.             PostfixList(retVal, firstRunner -> thing);
  603.             firstRunner = firstRunner -> next;
  604.         }
  605.         else
  606.         {
  607.             PostfixList(retVal, secondRunner -> thing);
  608.             secondRunner = secondRunner -> next;
  609.         }
  610.         }
  611.         else
  612.         {
  613.         if (comparison >= 0)
  614.         {
  615.             PostfixList(retVal, firstRunner -> thing);
  616.             firstRunner = firstRunner -> next;
  617.         }
  618.         else
  619.         {
  620.             PostfixList(retVal, secondRunner -> thing);
  621.             secondRunner = secondRunner -> next;
  622.         }
  623.         }
  624.     }
  625.  
  626.     /*Take care of fiddly bits at the end*/
  627.     while(firstRunner)
  628.     {
  629.         PostfixList(retVal, firstRunner -> thing);
  630.         firstRunner = firstRunner -> next;
  631.     }
  632.     while(secondRunner)
  633.     {
  634.         PostfixList(retVal, secondRunner -> thing);
  635.         secondRunner = secondRunner -> next;
  636.     }
  637.     }
  638.     return retVal;
  639. }
  640.  
  641. ObjPtr CleanupList(list)
  642. ObjPtr list;
  643. /*Method to clean up a list*/
  644. {
  645.     EmptyList(list);
  646.     return ObjTrue;
  647. }
  648.  
  649. void InitLists()
  650. /*Initializes lists*/
  651. {
  652.     listClass = NewList();
  653.     SetMethod(listClass, FINDOBJECT, FindListObject);
  654.     SetMethod(listClass, FORALLOBJECTS, ForAllListObjects);
  655.     SetMethod(listClass, MARK, MarkList);
  656.     SetMethod(listClass, PRESS, PressList);
  657.     SetMethod(listClass, TURNDIAL, TurnDialList);
  658.     SetMethod(listClass, CLEANUP, CleanupList);
  659.     AddToReferenceList(listClass);
  660. }
  661.  
  662. void KillLists()
  663. /*Destroys the lists*/
  664. {
  665.     DeleteThing(listClass);
  666. }
  667.  
  668.  
  669.